package com.shelpe.services.sinbad.controller.sinbad;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.shelpe.services.sinbad.controller.dto.AdgroupItem;
import com.shelpe.services.sinbad.controller.dto.page.ListMybatisPage;
import com.shelpe.services.sinbad.dto.AdgroupAndRptAdgroupDto.rptAdgroupVo;
import com.shelpe.services.sinbad.entity.jpa.Adgroup;
import com.shelpe.services.sinbad.entity.jpa.Campaign;
import com.shelpe.services.sinbad.entity.jpa.Category;
import com.shelpe.services.sinbad.entity.jpa.MobileAdgroupDetail;
import com.shelpe.services.sinbad.entity.jpa.MobileAdgroupDetail.Status;
import com.shelpe.services.sinbad.model.AdgroupWithRptAdgroupDto;
import com.shelpe.services.sinbad.model.RptKeyword;
import com.shelpe.services.sinbad.readdao.ReadRptKeywordMapper;
import com.shelpe.services.sinbad.repository.jpa.AdgroupRepository;
import com.shelpe.services.sinbad.repository.jpa.CampaignRepository;
import com.shelpe.services.sinbad.repository.jpa.CategoryRepository;
import com.shelpe.services.sinbad.repository.jpa.MobileAdgroupRespository;
import com.shelpe.services.sinbad.service.rpt.AdgroupService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

/**
 * 
 * @description
 * @author yechen@shelpe.com
 * @date 2018年3月15日上午10:00:28
 */
@RestController
@RequestMapping(value = "/sinbadservice/v2")
@Api("v2版推广组相关的API")
public class Adgroup2Controller {
	public final static Predicate[] TEMPLATE = new Predicate[0];

	@Autowired
	private AdgroupRepository adgroupRepository;
	@Autowired
	private AdgroupService adgroupService;
	@Autowired
	private CampaignRepository campaignRepository;
	@Autowired
	private ReadRptKeywordMapper readRptKeywordMapper;
	@Autowired
	private CategoryRepository categoryRepository;
	@Autowired
	private MobileAdgroupRespository mobileAdgroupRepository;

	@ApiOperation(value = "批量更新推广组(开车模式)")
	@RequestMapping(method = RequestMethod.PUT, path = "/campaigns/{campaign_id}/adgroups")
	public AdgroupItem updateAdgroups(@PathVariable("campaign_id") long campaignID,
			@RequestParam(name = "adgroup_ids", required = false) List<Long> adgroupIDs, @RequestBody AdgroupItem dto) {
		List<Adgroup> pos = this.adgroupRepository.findAll(new Specification<Adgroup>() {
			@Override
			public Predicate toPredicate(Root<Adgroup> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<Predicate>();
				predicates.add(cb.equal(root.get("campaignID"), campaignID));
				if (adgroupIDs != null && adgroupIDs.size() > 0) {
					predicates.add(root.<Long> get("autoID").in(adgroupIDs));
				}
				return cb.and(predicates.toArray(TEMPLATE));
			}
		});
		return this.adgroupService.updateAdgroups(pos, dto);
	}

	@ApiOperation(value = "查看某个推广组")
	@ApiResponses(@ApiResponse(code = 500, message = "invalid_adgroup_id"))
	@RequestMapping(method = RequestMethod.GET, path = "/adgroups/{adgroup_id}")
	public AdgroupItem findAdgroup(@PathVariable("adgroup_id") long adgroupID) {
		Assert.isTrue(adgroupID > 0, "invalid_adgroup_id");
		Adgroup adgroup = this.adgroupRepository.findOne(adgroupID);
		AdgroupItem dto = new AdgroupItem();
		if (adgroup == null) {
			return dto;
		}
		Campaign campaign = this.campaignRepository.findOne(adgroup.getCampaignID());
		if (campaign == null) {
			return dto;
		}
		dto.from(adgroup);
		dto.from(campaign);
		this.findByCatetoryName(dto, adgroup);

		return dto;
	}

	@ApiOperation(value = "获取推广组")
	@RequestMapping(method = RequestMethod.GET, path = "/users/{user_id}/adgroups")
	public ListMybatisPage<AdgroupItem> findAllAdgroup(@PathVariable("user_id") long userID,
			@RequestParam(name = "campaign_id", required = false, defaultValue = "0") long campaignID,
			@RequestParam(name = "page_num", defaultValue = "1") int page,
			@RequestParam(name = "page_size", defaultValue = "15") int size,
			@RequestParam(name = "sort", defaultValue = "adgroupStatus") String sort,
			@RequestParam(name = "direct", defaultValue = "desc") String direct,
			@RequestParam(name = "search_title", defaultValue = "", required = false) String title,
			@RequestParam(name = "days", required = false, defaultValue = "0") int days,
			@RequestParam(name = "start", required = false) String startDate,
			@RequestParam(name = "end", required = false) String endDate) {
		ListMybatisPage<AdgroupItem> dtos = new ListMybatisPage<AdgroupItem>();
		dtos.setContent(new ArrayList<AdgroupItem>());
		Date yesterday = DateUtils.addDays(DateUtils.truncate(new Date(), Calendar.DATE), -1);
		if (StringUtils.isBlank(startDate) && StringUtils.isBlank(endDate)) {
			startDate = DateFormatUtils.format(DateUtils.addDays(yesterday, -6), "yyyy-MM-dd");
			endDate = DateFormatUtils.format(yesterday, "yyyy-MM-dd");
		}
		if (days > 0) {
			startDate = DateFormatUtils.format(DateUtils.addDays(yesterday, -days + 1), "yyyy-MM-dd");
			endDate = DateFormatUtils.format(yesterday, "yyyy-MM-dd");
		}
		int limitStart = (page - 1) * size;

		String device = "mobile";
		List<AdgroupWithRptAdgroupDto> mobileDtos = new ArrayList<AdgroupWithRptAdgroupDto>();
		device = "pc";
		List<AdgroupWithRptAdgroupDto> pcDtos = new ArrayList<AdgroupWithRptAdgroupDto>();
		device = "all";
		List<AdgroupWithRptAdgroupDto> AllDtos = new ArrayList<AdgroupWithRptAdgroupDto>();
		if (campaignID > 0) {
			/** 1，2表示pc，4，5表示mobile */
			mobileDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(0, campaignID, startDate, endDate, 4, 5,
					sort, direct, limitStart, size, device, title);
			pcDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(0, campaignID, startDate, endDate, 1, 2,
					sort, direct, limitStart, size, device, title);
			AllDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(0, campaignID, startDate, endDate, 1, 5,
					sort, direct, limitStart, size, device, title);
		} else {
			mobileDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(userID, 0, startDate, endDate, 4, 5,
					sort, direct, limitStart, size, device, title);
			pcDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(userID, 0, startDate, endDate, 1, 2, sort,
					direct, limitStart, size, device, title);
			AllDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(userID, 0, startDate, endDate, 1, 5, sort,
					direct, limitStart, size, device, title);
		}
		Map<Long, AdgroupItem> dtoMap = new HashMap<Long, AdgroupItem>();
		for (AdgroupWithRptAdgroupDto adgroup : AllDtos) {
			AdgroupItem dto = new AdgroupItem();
			dto.fromAdgroup(adgroup);
			dto.setAll(new rptAdgroupVo());
			dto.setMobile(new rptAdgroupVo());
			dto.setPc(new rptAdgroupVo());
			dto.from(adgroup, dto.getAll());
			dtoMap.put(adgroup.getAdgroupId(), dto);
			dtos.getContent().add(dto);
		}
		for (AdgroupWithRptAdgroupDto adgroup : mobileDtos) {
			AdgroupItem dto = dtoMap.get(adgroup.getAdgroupId());
			if (dto != null) {
				dto.from(adgroup, dto.getMobile());
			}
		}
		for (AdgroupWithRptAdgroupDto adgroup : pcDtos) {
			AdgroupItem dto = dtoMap.get(adgroup.getAdgroupId());
			if (dto != null) {
				dto.from(adgroup, dto.getPc());
			}
		}

		/** 获取数据的汇总数 */
		int sum = 0;
		if (campaignID > 0) {
			sum = this.readRptKeywordMapper.countByAdgroupAndRptAdgroup(0, campaignID, startDate, endDate, 1, 5, title);
		} else {
			sum = this.readRptKeywordMapper.countByAdgroupAndRptAdgroup(userID, 0, startDate, endDate, 1, 5, title);
		}
		dtos.from(page, size, sum, dtos.getContent().size());

		return dtos;
	}

	@ApiOperation(value = "用户级别批量获取推广组(未分页)")
	@RequestMapping(method = RequestMethod.GET, path = "/users/{user_id}/adgroups/@rpt")
	public List<AdgroupItem> query(@PathVariable("user_id") final long userID,
			@RequestParam(name = "campaign_id", required = false, defaultValue = "0") final long campaignID,
			@RequestParam(name = "adgroup_id", required = false, defaultValue = "0") final long adgroupID,
			@RequestParam(name = "start", required = false) String start,
			@RequestParam(name = "end", required = false) String end) {
		List<Adgroup> pos = this.adgroupService.findAdgroup(userID, campaignID, adgroupID);

		List<AdgroupItem> dtos = new ArrayList<AdgroupItem>();
		if (pos == null || pos.size() == 0) {
			return dtos;
		}

		int limitStart = 0;
		int limitEnd = 16000; // 推广组最大值16000
		String sort = "adgroupStatus"; // 默认推广状态排序
		String direct = "desc";
		Date yesterday = DateUtils.addDays(DateUtils.truncate(new Date(), Calendar.DATE), -1);

		if (StringUtils.isBlank(start) && StringUtils.isBlank(end)) {// 默认7天
			start = DateFormatUtils.format(DateUtils.addDays(yesterday, -6), "yyyy-MM-dd");
			end = DateFormatUtils.format(yesterday, "yyyy-MM-dd");
		}

		String device = "mobile";
		List<AdgroupWithRptAdgroupDto> mobileDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(0,
				campaignID, start, end, 4, 5, sort, direct, limitStart, limitEnd, device, null);

		device = "pc";
		List<AdgroupWithRptAdgroupDto> pcDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(0, campaignID,
				start, end, 1, 2, sort, direct, limitStart, limitEnd, device, null);
		/** 1，2表示pc，4，5表示mobile */

		device = "all";
		List<AdgroupWithRptAdgroupDto> AllDtos = this.readRptKeywordMapper.selectByAdgroupAndRptAdgroup(0, campaignID,
				start, end, 1, 5, sort, direct, limitStart, limitEnd, device, null);
		Map<Long, AdgroupItem> dtoMap = new HashMap<Long, AdgroupItem>();
		// 可养分的宝贝ID
		Map<Long, RptKeyword> adgroupIDs = new HashMap<Long, RptKeyword>();
		Map<Long, MobileAdgroupDetail> mapMobileAdgroups = new HashMap<Long, MobileAdgroupDetail>();
		List<MobileAdgroupDetail> mobileAdgroups = new ArrayList<MobileAdgroupDetail>();
		if (campaignID > 0) {
			mobileAdgroups = mobileAdgroupRepository.findByCampaignIDAndStatus(campaignID, Status.starting);
			for (MobileAdgroupDetail mobileAdgroup : mobileAdgroups) {
				mapMobileAdgroups.put(mobileAdgroup.getAdgroupID(), mobileAdgroup);
			}
			adgroupIDs = this.adgroupService.mobileAdgroupIDs(campaignID);
		}
		for (AdgroupWithRptAdgroupDto adgroup : AllDtos) {
			AdgroupItem dto = new AdgroupItem();
			if (adgroupIDs.get(adgroup.getAdgroupId()) != null && adgroup.getDriveType() != 2
					&& adgroup.getAdgroupStatus() == 4) {
				dto.setMobileMark(1);
			}
			// 养分中的宝贝
			if (mapMobileAdgroups.get(adgroup.getAdgroupId()) != null) {
				dto.setMobileMark(2);
				dto.setMobileAdgroupID(mapMobileAdgroups.get(adgroup.getAdgroupId()).getAutoID());
			}
			dto.fromAdgroup(adgroup);
			dto.setAll(new rptAdgroupVo());
			dto.setMobile(new rptAdgroupVo());
			dto.setPc(new rptAdgroupVo());
			BeanUtils.copyProperties(adgroup, dto.getAll());
			dtoMap.put(adgroup.getAdgroupId(), dto);
			dtos.add(dto);
		}
		for (AdgroupWithRptAdgroupDto adgroup : mobileDtos) {
			AdgroupItem dto = dtoMap.get(adgroup.getAdgroupId());
			if (dto != null) {
				BeanUtils.copyProperties(adgroup, dto.getMobile());
			}
		}
		for (AdgroupWithRptAdgroupDto adgroup : pcDtos) {
			AdgroupItem dto = dtoMap.get(adgroup.getAdgroupId());
			if (dto != null) {
				BeanUtils.copyProperties(adgroup, dto.getPc());
			}
		}

		return dtos;
	}

	@ApiOperation(value = "批量获取推广组")
	@RequestMapping(method = RequestMethod.GET, path = "/campaigns/{campaign_id}/adgroups")
	public List<AdgroupItem> query(@PathVariable("campaign_id") final long campaignID,
			@RequestParam(name = "adgroup_id", required = false, defaultValue = "0") final long adgroupID,
			@RequestParam(name = "need_rpt", required = false, defaultValue = "false") boolean needRpt,
			@RequestParam(name = "start", required = false) String start,
			@RequestParam(name = "end", required = false) String end,
			@RequestParam(name = "device", required = false, defaultValue = "all") String device) {
		List<Adgroup> pos = this.adgroupRepository.findAll(new Specification<Adgroup>() {
			@Override
			public Predicate toPredicate(Root<Adgroup> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				Predicate p = cb.equal(root.get("campaignID"), campaignID);
				if (adgroupID > 0) {
					p = cb.and(p, cb.equal(root.get("autoID"), adgroupID));
				}
				return p;
			}
		});

		List<AdgroupItem> dtos = new ArrayList<AdgroupItem>();
		if (pos == null || pos.size() == 0) {
			return dtos;
		}

		Map<Long, AdgroupItem> dtoMap = new HashMap<Long, AdgroupItem>();
		if (pos != null && pos.size() > 0) {
			List<Long> campaignIDs = new ArrayList<Long>();
			for (Adgroup po : pos) {
				if (campaignIDs.indexOf(po.getCampaignID()) == -1) {
					campaignIDs.add(po.getCampaignID());
				}
			}
			List<Campaign> campaigns = this.campaignRepository.findByAutoIDIn(campaignIDs);
			Map<Long, Campaign> campaignMap = new HashMap<Long, Campaign>();
			if (campaigns != null && campaigns.size() > 0) {
				for (Campaign campaign : campaigns) {
					campaignMap.put(campaign.getAutoID(), campaign);
				}
			}
			for (Adgroup po : pos) {
				AdgroupItem dto = new AdgroupItem();
				Campaign campaign = campaignMap.get(po.getCampaignID());
				if (campaign != null) {
					dto.setCampaignName(campaign.getTitle());
				}
				dto.from(po);
				dtoMap.put(po.getAutoID(), dto);
				dtos.add(dto);
			}
		}

		if (needRpt) {
			if (pos != null && pos.size() > 0) {
				for (Adgroup po : pos) {
					AdgroupItem dto = dtoMap.get(po.getAutoID());
					if (dto != null) {
						// TODO:需优化
						dto.setEffect(this.adgroupService.report(dto.getAdgroupID(), device, 0, start, end));
					}

				}
			}
		}
		return dtos;
	}

	/************************** 辅助方法 ****************************************/
	private void findByCatetoryName(AdgroupItem dto, Adgroup adgroup) {
		String[] arr = adgroup.getCategoryIDs().split(" ");
		Long[] longs = new Long[arr.length];
		for (int i = 0; i < arr.length; i++) {
			longs[i] = Long.parseLong(arr[i]);
		}
		List<Long> catIDs = java.util.Arrays.asList(longs);
		List<Category> categorys = this.categoryRepository.findByCategoryIDInOrderByLevelAsc(catIDs);
		Assert.notNull(categorys, "invalid_category");
		if (categorys.size() > 1) {
			String catName = "";
			for (Category cat : categorys) {
				if (StringUtils.isBlank(catName)) {
					catName = cat.getName();
				} else {
					catName = catName + ">" + cat.getName();
				}
			}
			dto.setCategoryName(catName);
		} else {
			dto.setCategoryName(categorys.get(0).getName());
		}
	}
}
